﻿using System;
using System.Collections.Generic;

using System.Text;
using System.IO;
using System.Drawing;
using System.Collections;

namespace MSL.Utility.Images
{
    /// <summary>
    ///  图像操作类(主要用于给图片加上透明文字水印与图片水印)  
    ///  调用示例：1.water.ImageWatermark("D:/8.jpg","D:/2.png", "D:/_2.png",MSL.Utility.Images.Water.ImagePosition.RigthBottom)
    ///            2.water.LetterWatermark("D:/8.jpg","D:/_22.png", 15, "我喜欢你呀！", 
    ///            System.Drawing.Color.FromArgb(255, 234,32),MSL.Utility.Images.Water.ImagePosition.RigthBottom)
    /// </summary>
    public class Water
    {
        private String _fontType = "Arial";//文字水印字体类型
        private String _ErrMsg;//出错信息

        #region 属性
        /// <summary>
        /// 字体类型
        /// </summary>
        public string FontType
        {
            get { return _fontType; }
            set { _fontType = value; }
        }
        /// < summary>  
        /// 出错信息  
        /// < /summary>  
        public string ErrMsg
        {
            get { return _ErrMsg; }
            set { _ErrMsg = value; }
        }
        #endregion

        #region 水印位置
        /// < summary>  
        /// 水印位置  
        /// < /summary>  
        public enum ImagePosition
        {
            /**/
            /// < summary>  
            /// 左上  
            /// < /summary>  
            LeftTop,
            /// < summary>  
            /// 上  
            /// < /summary>  
            Top,
            /**/
            /// < summary>  
            /// 左下  
            /// < /summary>  
            LeftBottom,
            /**/
            /// < summary>  
            /// 左中 
            /// < /summary>  
            LeftCenter,
            /**/
            /// < summary>  
            /// 右中 
            /// < /summary>  
            RightCenter,
            /**/
            /// < summary>  
            /// 右上  
            /// < /summary>  
            RightTop,
            /**/
            /// < summary>  
            /// 右下  
            /// < /summary>  
            RigthBottom,
            /**/
            /// < summary>  
            /// 顶部居中  
            /// < /summary>  
            TopMiddle,
            /**/
            /// < summary>  
            /// 底部
            /// < /summary>  
            Bottom,
            /**/
            /// < summary>  
            /// 中心  
            /// < /summary>  
            Center
        }
        #endregion

        #region 私有方法
        #region 将文件转换成流
        /// < summary>  
        /// 将文件转换成流  
        /// < /summary>  
        /// < param name="fileName">文件全路径< /param>  
        /// < returns>< /returns>  
        private Byte[] SetImageToByteArray(string fileName)
        {
            byte[] image = null;
            try
            {
                using (FileStream fs = new FileStream(fileName, FileMode.Open))
                {
                    FileInfo fileInfo = new FileInfo(fileName);
                    int streamLength = (int)fs.Length;
                    image = new byte[streamLength];
                    fs.Read(image, 0, streamLength);
                    return image;
                }
            }
            catch
            {
                return null;
            }
        }
        #endregion

        #region 将byte转换成MemoryStream类型
        /// < summary>  
        /// ASP.NET图片加水印：将byte转换成MemoryStream类型  
        /// < /summary>  
        /// < param name="mybyte">byte[]变量< /param>  
        /// < returns>< /returns>  
        private MemoryStream ByteToStream(byte[] mybyte)
        {
            MemoryStream mymemorystream = new MemoryStream(mybyte, 0, mybyte.Length);
            return mymemorystream;
        }
        #endregion

        #region 将byte转换成Image文件
        /// < summary>  
        /// ASP.NET图片加水印：将byte转换成Image文件  
        /// < /summary>  
        /// < param name="mybyte">byte[]变量< /param>  
        /// < returns>< /returns>  
        private System.Drawing.Image SetByteToImage(byte[] mybyte)
        {
            MemoryStream mymemorystream = new MemoryStream(mybyte, 0, mybyte.Length);
            return System.Drawing.Image.FromStream(mymemorystream);
        }
        #endregion
        #endregion

        #region 图片水印
        /// <summary>
        /// 图片水印处理方法
        /// </summary>
        /// <param name="path">需要加载水印的图片路径（绝对路径）</param>
        /// <param name="waterPath">水印图片（绝对路径）</param>
        /// <param name="outPath">生成图片路径（绝对路径）</param>
        /// <param name="position">水印位置</param>
        public bool ImageWatermark(string path, string waterPath, string outPath, ImagePosition position)
        {
            DateTime time = DateTime.Now;
            string filename = "" + time.Year.ToString() + time.Month.ToString() + time.Day.ToString() + time.Hour.ToString() + time.Minute.ToString() + time.Second.ToString() + time.Millisecond.ToString();
            try
            {
                using (Image img = Bitmap.FromFile(path))
                {
                    using (Image waterimg = Image.FromFile(waterPath))
                    {
                        using (Graphics g = Graphics.FromImage(img))
                        {
                            if (File.Exists(outPath))
                                File.Delete(outPath);

                            ArrayList loca = GetLocation(position, img, waterimg);
                            g.DrawImage(waterimg, new Rectangle(int.Parse(loca[0].ToString()), int.Parse(loca[1].ToString()), waterimg.Width, waterimg.Height));
                            img.Save(outPath);

                            if (File.Exists(outPath))
                                return true;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception("", e);
            }
            return true;
        }

        /// <summary>
        /// 图片水印位置处理方法
        /// </summary>
        /// <param name="position">水印位置</param>
        /// <param name="img">需要添加水印的图片</param>
        /// <param name="waterimg">水印图片</param>
        private ArrayList GetLocation(ImagePosition position, Image img, Image waterimg)
        {
            ArrayList loca = new ArrayList();
            int x = 0;
            int y = 0;

            switch (position)
            {
                case ImagePosition.LeftTop:
                    x = 10;
                    y = 10;
                    break;
                case ImagePosition.Top:
                    x = img.Width / 2 - waterimg.Width / 2;
                    y = img.Height - waterimg.Height;
                    break;
                case ImagePosition.LeftBottom:
                    x = 10;
                    y = img.Height - waterimg.Height;
                    break;
                case ImagePosition.LeftCenter:
                    x = 10;
                    y = img.Height / 2 - waterimg.Height / 2;
                    break;
                case ImagePosition.RightCenter:
                    x = img.Width - waterimg.Width;
                    y = img.Height / 2 - waterimg.Height / 2;
                    break;
                case ImagePosition.RightTop:
                    x = img.Width - waterimg.Width;
                    y = 10;
                    break;
                case ImagePosition.RigthBottom:
                    x = img.Width - waterimg.Width;
                    y = img.Height - waterimg.Height;
                    break;
                case ImagePosition.TopMiddle:
                    break;
                case ImagePosition.Bottom:
                    x = img.Width / 2 - waterimg.Width / 2;
                    y = img.Height - waterimg.Height;
                    break;
                case ImagePosition.Center:
                    x = img.Width / 2 - waterimg.Width / 2;
                    y = img.Height / 2 - waterimg.Height / 2;
                    break;
                default:
                    x = img.Width - waterimg.Width;
                    y = img.Height - waterimg.Height;
                    break;
            }
            loca.Add(x);
            loca.Add(y);
            return loca;
        }
        #endregion

        #region 文字水印
        /// <summary>
        /// 文字水印处理方法
        /// </summary>
        /// <param name="path">图片路径（绝对路径）</param>
        /// <param name="waterPath">水印图片（绝对路径）</param>
        /// <param name="size">字体大小</param>
        /// <param name="letter">水印文字</param>
        /// <param name="color">颜色</param>
        /// <param name="position">水印位置</param>
        public bool LetterWatermark(string path, string outPath, int size, string letter, Color color, ImagePosition position)
        {
            #region

            DateTime time = DateTime.Now;
            string filename = "" + time.Year.ToString() + time.Month.ToString() + time.Day.ToString() + time.Hour.ToString() + time.Minute.ToString() + time.Second.ToString() + time.Millisecond.ToString();

            try
            {
                using (Image img = Bitmap.FromFile(path))
                {
                    using (Graphics gs = Graphics.FromImage(img))
                    {
                        if (File.Exists(outPath))
                            File.Delete(outPath);

                        ArrayList loca = GetLocation(position, img, size, letter.Length);
                        using (Brush br = new SolidBrush(color))
                        {
                            gs.DrawString(letter, new Font("宋体", size), br, float.Parse(loca[0].ToString()), float.Parse(loca[1].ToString()));
                            img.Save(outPath);

                            if (File.Exists(outPath))
                                return true;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception("", e);
            }
            return true;

            #endregion
        }

        /// <summary>
        /// 图片水印位置的方法
        /// </summary>
        /// <param name="position">位置代码</param>
        /// <param name="img">图片对象</param>
        /// <param name="width">宽(当水印类型为文字时,传过来的就是字体的大小)</param>
        /// <param name="height">高(当水印类型为文字时,传过来的就是字符的长度)</param>
        private ArrayList GetLocation(ImagePosition position, Image img, int width, int height)
        {
            #region

            ArrayList loca = new ArrayList();  //定义数组存储位置
            float x = 10;
            float y = 10;

            switch (position)
            {
                case ImagePosition.LeftTop:
                    loca.Add(x);
                    loca.Add(y);
                    break;
                case ImagePosition.Top:
                    x = img.Width / 2 - (width * height) / 2;
                    loca.Add(x);
                    loca.Add(y);
                    break;
                case ImagePosition.LeftBottom:
                    y = img.Height - width - 5;
                    break;
                case ImagePosition.LeftCenter:
                    y = img.Height / 2;
                    break;
                case ImagePosition.RightCenter:
                    x = img.Width - height;
                    y = img.Height / 2;
                    break;
                case ImagePosition.RightTop:
                    x = img.Width - width * height;
                    break;
                case ImagePosition.RigthBottom:
                    x = img.Width - width * height;
                    y = img.Height - width - 5;
                    break;
                case ImagePosition.TopMiddle:
                    break;
                case ImagePosition.Bottom:
                    x = img.Width / 2 - (width * height) / 2;
                    y = img.Height - width - 5;
                    break;
                case ImagePosition.Center:
                    x = img.Width / 2 - (width * height) / 2;
                    y = img.Height / 2;
                    break;
                default:
                    x = img.Width - width * height;
                    y = img.Height - width - 5;
                    break;
            }

            loca.Add(x);
            loca.Add(y);
            return loca;

            #endregion
        }
        #endregion
    }
}
